﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Facebook;
using System.Diagnostics;
using System.Dynamic;
using System.Configuration;
using BicycleTrafficSimulator.DataModel;

namespace BicycleTrafficSimulator
{
    public partial class LoginForm : Form
    {
        private static LoginForm instance;

        DataBase db = new DataBase();
        User user;
        Score initialScore;

        private bool scoreUpdateInitiated = false;

        public bool ScoreUpdateInitiated
        {
            get { return scoreUpdateInitiated; }
            set { scoreUpdateInitiated = value; }
        }

        public User User
        {
            get { return user; }
            set { user = value; }
        }

        bool startGame = false;
        bool closed = false;

        public bool ClosedBool
        {
            get { return closed; }
            set { closed = value; }
        }

        public bool StartGame
        {
            get { return startGame; }
            set { startGame = value; }
        }

        private int registerClick = 0;

        private LoginForm()
        {
            InitializeComponent();
            //startGame = false;
            initialScore = new Score();

            this.FormClosing += new FormClosingEventHandler(LoginForm_FormClosing);

            ageTextBox.Hide();
            birthYearLabel.Hide();
            specLabel.Hide();

        }

        public static LoginForm Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new LoginForm();
                }
                return instance;
            }
        }

        public string ApplicationId
        {
            get
            {
                return ConfigurationManager.AppSettings["ApplicationId"];
            }
        }

        public string ExtendedPermissions
        {
            get
            {
                return ConfigurationManager.AppSettings["ExtendedPermissions"];
            }
        }

        public string AppSecret
        {
            get
            {
                return ConfigurationManager.AppSettings["ApplicationSecret"];
            }
        }

        public string AccessToken { get; set; }

        private Uri GenerateLoginUrl(string appId, string extendedPermissions)
        {
            // for .net 3.5
            // var parameters = new Dictionary<string,object>
            // parameters["client_id"] = appId;
            dynamic parameters = new ExpandoObject();
            parameters.client_id = appId;
            parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";

            // The requested response: an access token (token), an authorization code (code), or both (code token).
            parameters.response_type = "token";

            // list of additional display modes can be found at http://developers.facebook.com/docs/reference/dialogs/#display
            parameters.display = "popup";

            // add the 'scope' parameter only if we have extendedPermissions.
            if (!string.IsNullOrWhiteSpace(extendedPermissions))
                parameters.scope = extendedPermissions;

            // generate the login url
            var fb = new FacebookClient();
            return fb.GetLoginUrl(parameters);
        }

        private void WebBrowser_Load(object sender, EventArgs e)
        {
            webBrowser.Navigated += WebBrowserNavigated;
            webBrowser.Navigate(this.GenerateLoginUrl(ApplicationId, ExtendedPermissions));
        }

        private void WebBrowserNavigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            /// whenever the browser navigates to a new url, try parsing the url
            // the url may be the result of OAuth 2.0 authentication.
            var facebk = new FacebookClient();
            FacebookOAuthResult oauthResult;
            if (facebk.TryParseOAuthCallbackUrl(e.Url, out oauthResult))
            {
                // The url is the result of OAuth 2.0 authentication.
                if (oauthResult.IsSuccess)
                {
                    var accesstoken = oauthResult.AccessToken;
                    AccessToken = accesstoken;
                    getUserIdInfo(accesstoken);
                    Debug.WriteLine("true oauthResult");
                    //  webBrowser.Navigate(this.GenerateLogoutUrl(accesstoken));
                }
                else
                {
                    this.Close();
                    Debug.WriteLine("false oauthResult");
                }
            }

        }

        private void getUserIdInfo(string accessToken)
        {
            var fb = new FacebookClient(accessToken);

            dynamic response = fb.Get("me");
            var birthYear = Convert.ToDateTime(response.birthday).Year;
            DateTime dt = DateTime.Now;
            int age = dt.Year - birthYear;
            user = new User(response.first_name, age, initialScore);
            db.AddUser(user);

            startGame = true;
            this.Hide();
        }

        public void PostToFeed(String message)
        {
            Post(AccessToken, message);
        }

        private void Post(string accessToken, string message)
        {
            var fb = new FacebookClient(accessToken);

            dynamic response = fb.Post("me/feed", new { message = message });
            var newPostId = response.id;
        }

        protected Uri GenerateLogoutUrl(string accessToken)
        {

            var oauth = new FacebookClient();
            var logoutParameters = new Dictionary<string, object> { { "access_token", accessToken }, { "next", "http://www.facebook.com" } };

            var logoutUrl = oauth.GetLogoutUrl(logoutParameters);
            return logoutUrl;
        }

        public void CloseWindow()
        {
            this.Close();
            ClosedBool = true;
        }

        private void registerButton_Click(object sender, EventArgs e)
        {
            registerClick += 1;
            if (registerClick == 1)
            {
                ageTextBox.Show();
                birthYearLabel.Show();
                specLabel.Show();
            }
            else if (registerClick == 2)
            {
                registerClick = 0;
                string firstName = nameTextBox.Text;
                if (String.IsNullOrEmpty(firstName))
                    MessageBox.Show("Please fulfill name");
                nameTextBox.Clear();

                string ageString = ageTextBox.Text;
                if (String.IsNullOrEmpty(ageString))
                    MessageBox.Show("Don't forget to write your birth year also! :)");
                else
                {
                    DateTime dt = DateTime.Now;
                    int age = Convert.ToInt16(ageString);
                    ageTextBox.Clear();
                    User aux = new User(firstName, age, initialScore);
                    if (db.existsUser(aux))
                        MessageBox.Show("User already exists. Try another name!");
                    else
                    {
                        db.AddUser(aux);
                        if (!db.existsUser(aux))
                            MessageBox.Show("Registration failed. Please try again!");
                        else
                            user = aux;
                        startGame = true;
                        this.Hide();
                    }

                    db.ReadUsers();
                }
            }
        }


        private void loginButton_Click(object sender, EventArgs e)
        {
            db.ReadUsers();
            string firstName = nameTextBox.Text;
            if (String.IsNullOrEmpty(firstName))
                MessageBox.Show("Name cannot be empty");
            nameTextBox.Clear();
            User aux = new User(firstName, 0, initialScore);
            if (db.existsUser(aux))
            {
                user = db.readUser(aux);
                startGame = true;
                this.Hide();
            }
            else
            {
                MessageBox.Show("User does not exist. Register first!");
                firstName = "";
            }

        }

        private void loginFacebookButton_Click(object sender, EventArgs e)
        {
            this.titleLabel.Hide();
            this.childrenPictureBox.Hide();
            this.firstNameLabel.Hide();
            this.nameTextBox.Hide();
            this.birthYearLabel.Hide();
            this.ageTextBox.Hide();
            this.specLabel.Hide();
            this.registerButton.Hide();
            this.loginButton.Hide();
            this.loginFacebookButton.Hide();

            this.WebBrowser_Load(sender, e);
        }

        private void backButton_Click(object sender, EventArgs e)
        {
            ClosedBool = true;
        }


        void LoginForm_FormClosing(object sender, FormClosingEventArgs e)
        {

            //ClosedBool = true;
            Application.Exit();

        }



        public int UpdateScore(User _user)
        {
            ScoreUpdateInitiated = true;
            Score newScore = _user.Score;
            int safeValue = newScore.Value;
            User aux = db.readUser(_user);
            if (aux.Score.Value < safeValue)
            {
                db.UpdateUserScore(user, safeValue);
                return safeValue;
            }
            else
            {
                return aux.Score.Value;
            }
        }

        private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {

        }
    }
}
